//大括号是对象数组 中括号是元素数组{x:10,y:0} ['t','a']

//关节 模型对象 数组
var robotLink = [];
// 模型对应的点位缓存
var robotLinkPosition = [];
// 模型对应的旋转缓存
var robotLinkRotation = [];
// link数量
var robotLinkCount;

//关节之间的关系是否初始化完成
var linkRelation = false;

//机器人参数初始化
robotLinkCount = 6+2;       //6关节 + 底座和手
robotScale = 0.001;         //模型比例
//位置偏置补偿 type 机器人类型 linkNumber轴编号:根据不同情况修改设置
var robotOffsetPosX = [0,0,0,0,0,0,0,0];
var robotOffsetPosY = [0,0,0,0,0,0,-60,60];
var robotOffsetPosZ = [0,0,340,180,215,180,220,95];
//var robotOffsetPosZ = [0,0,0,0,0,0,0,0];

var robotOffsetRotX = [-Math.PI/2,0,0,0,0,0,0,0];
var robotOffsetRotY = [0,0,0,0,0,0,0,Math.PI/2];
var robotOffsetRotZ = [0,0,0,0,0,0,0,0];

//*******************************************************
//关节是否运动:随机运动
var linkRandamRun = {runSwitch:false} ;

var kinematicsTween;
var tweenParameters = [];

//*******************************************************
//相机位置,是否运动
var cameraRun = {runSwitch:true} ;
// var cameraPosition = { x : 3, y: 3 , z :3};//默认3 0 3
var cameraPosition = { x : 1.8, y: 3 , z :1.8};//默认3 0 3
// var cameraVector = { x : 0, y: 0 , z :0};//默认3 0 3
var cameraVector = { x : 0, y: 0.5 , z :0};//默认3 0 3

//3D模型显示部分*****************************************
// 检查浏览器
if (!Detector.webgl) Detector.addGetWebGLMessage();

// 初始化定义 html的dom操作 帧率监视器 控制器 辅助线 相机控制器
var container, stats, controlsGui, axes ,controlsCamera;
var containerSize = {w:0,h:0};//缓存判断用
// 相机 相机目标 场景 渲染
var camera, cameraTarget, scene, renderer;

// 初始化
init();
// 动画操作
animate();

function init() {
    // html 操作
    container = document.getElementById("setting_content");//自己改:对某个id操作
    // console.log(container.offsetWidth);
    // console.log(container.offsetHeight);
    // 
    // 相机
    //camera = new THREE.PerspectiveCamera(35, window.innerWidth / window.innerHeight, 1, 15);
    camera = new THREE.PerspectiveCamera(35, container.offsetWidth / container.offsetHeight, 1, 15);
    camera.position.set(cameraPosition.x, cameraPosition.y, cameraPosition.z);//相机的空间坐标
    cameraTarget = new THREE.Vector3(cameraVector.x, cameraVector.y, cameraVector.z);//相机为中心的旋转 0 0 0就是正对物体

    /*** 控制照像机 ***/
    // controlsCamera = new THREE.TrackballControls(camera); // 将照相机添加到控制器

    // 场景
    scene = new THREE.Scene();
    // scene.fog = new THREE.Fog(0x72645b, 2, 15); //地板颜色
    
    // 底部网格
    var grid = new THREE.GridHelper( 10, 10 );
    grid.position.y = 0;//跟plane一样
    scene.add( grid );//底部的网格

    // Ground 地板
    // var plane = new THREE.Mesh(
    //     new THREE.PlaneBufferGeometry(40, 40),
    //     new THREE.MeshPhongMaterial({
    //         color: 0x999999,
    //         specular: 0x101010
    //     })
    // );
    // plane.rotation.x = -Math.PI / 2;
    // plane.position.y = 0;//??为什么调低0.5位置……
    // scene.add(plane);
    // plane.receiveShadow = true;


    //加载所有关节
    for(var i = 0; i < robotLinkCount; i++)
    {
        // 初始化
        var tmpPosition = {x:robotOffsetPosX[i], y:robotOffsetPosY[i], z:robotOffsetPosZ[i] };
        var tmpRotation = {x:robotOffsetRotX[i], y:robotOffsetRotY[i], z:robotOffsetRotZ[i] };
        axisObjectInit(i,tmpPosition,tmpRotation);
    }

    // Lights 光线
    // scene.add( new THREE.HemisphereLight( 0xffeeee, 0x111122 ) );//半球光源
    // scene.add( new THREE.AmbientLight( 0xAEEEEE ) ); //环境光
    // 原本
    scene.add(new THREE.HemisphereLight(0x443333, 0x111122));//半球光源
    addShadowedLight(1, 1, 1, 0xffffff, 1.35);//白光 有阴影
    addShadowedLight(0.5, 1, -1, 0xffaa00, 1);//黄光 有阴影
    
    // renderer 渲染
    renderer = new THREE.WebGLRenderer({
        antialias: true//抗锯齿 平滑 默认false
    });
    // renderer.setClearColor(scene.fog.color); //地板颜色 暂时关闭渲染
    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.setSize(container.offsetWidth , container.offsetHeight);
    
    renderer.gammaInput = true; //暂时关闭渲染 影子相关等
    renderer.gammaOutput = true;
    renderer.shadowMap.enabled = true;
    renderer.shadowMap.renderReverseSided = false;

    container.appendChild(renderer.domElement);
    

    /* 辅助工具的初始化 */
    // stats帧率监视器
    stats = new Stats();
    container.appendChild(stats.dom);

    // //生成gui并添加参数
    controlsGui = new dat.GUI();//= new DAT.GUI({height : 5 * 32 - 1});
    controlsGui.addFolder( "cameraPosition" );
    controlsGui.add(cameraRun,"runSwitch");
    controlsGui.add(cameraPosition,"x",-10,10);
    controlsGui.add(cameraPosition,"y",-10,10);
    controlsGui.add(cameraPosition,"z",-10,10);
    
    controlsGui.addFolder( "cameraVector" );
    controlsGui.add(cameraVector,"x",-10,10);
    controlsGui.add(cameraVector,"y",-10,10);
    controlsGui.add(cameraVector,"z",-10,10);
    
    controlsGui.addFolder( "RandamRun" );
    controlsGui.add(linkRandamRun,"runSwitch");

    //坐标轴辅助
    //x 红 y 绿 z 蓝
    // axes = new THREE.AxisHelper(10);  
    // scene.add(axes);
    
    //监听窗口变化(改为定时器自己判断)
    // window.addEventListener('resize', onWindowResize, false);

    //补间动画
    setupTweenJoint();
}

function axisObjectInit(linkNumber,position,rotation){
    var loader = new THREE.STLLoader();
    // 用于表面有光泽的材料 Phong网孔材料
    // olor 线条的十六进制颜色。缺省值为 0xffffff
    // specular 设置高亮颜色，缺省为 0x111111
    // shininess 设置亮度，缺省为 30
    var material = new THREE.MeshPhongMaterial({
        color: 0xAAAAAA,
        specular: 0x111111,
        shininess: 200
    });
    // var material = new THREE.MeshStandardMaterial({//标准网孔 test
    //     color: 0xAAAAAA
    // });

    var fileName = 'stl/model/iiwa7-Basis-Flansch-J' + linkNumber + '.STL';
    console.log(linkNumber +'-load:' + fileName);
    //console.log(robotLink.length);
    loader.load(fileName, function(geometry) {
        robotLink[linkNumber] = new THREE.Mesh(geometry, material);
         
        robotLink[linkNumber].position.set(position.x, position.y, position.z);//位置初始化
        robotLink[linkNumber].rotation.set(rotation.x, rotation.y, rotation.z);//旋转初始化
        if(linkNumber == 0)
        {
            //因为设置连杆模型后，子关系的模型会根据父关系的比例进行变化
            //因此只需要设置父模型便可
            //如果是非连杆模型，就每一个都需要设置比例大小 (if注释便可)
            robotLink[linkNumber].scale.set(robotScale, robotScale, robotScale);//比例控制
        }
        
        robotLink[linkNumber].castShadow = true;//光对地面的阴影(有背景时候用)
        robotLink[linkNumber].receiveShadow = true;//光自己物体上的阴影(有背景时候用)

        scene.add(robotLink[linkNumber]);
    });

    robotLinkPosition[linkNumber] = {x:position.x, y:position.y, z:position.z};
    robotLinkRotation[linkNumber] = {x:rotation.x, y:rotation.y, z:rotation.z};
}

function addShadowedLight(x, y, z, color, intensity) {
    var directionalLight = new THREE.DirectionalLight(color, intensity);
    directionalLight.position.set(x, y, z);
    scene.add(directionalLight);
    directionalLight.castShadow = true;
    var d = 1;
    directionalLight.shadow.camera.left = -d;
    directionalLight.shadow.camera.right = d;
    directionalLight.shadow.camera.top = d;
    directionalLight.shadow.camera.bottom = -d;
    directionalLight.shadow.camera.near = 1;
    directionalLight.shadow.camera.far = 4;
    directionalLight.shadow.mapSize.width = 1024;
    directionalLight.shadow.mapSize.height = 1024;
    directionalLight.shadow.bias = -0.005;
}

function onWindowResize() {
    console.log("onWindowResize" + container.offsetWidth+" ; "+container.offsetHeight);
    
    camera.aspect = container.offsetWidth / container.offsetHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(container.offsetWidth , container.offsetHeight);
}

function checkWindowResize() {
    // if(container.offsetWidth <= 0 || container.offsetHeight <= 0 )
    // {
    //     return;
    // }
    // else
    // {
        if(containerSize.w != container.offsetWidth ||containerSize.h  != container.offsetHeight)
        {
            console.log("w:"+container.offsetWidth+" ; h:"+container.offsetHeight);
        
            //重置 窗口宽高
            onWindowResize();

            //重置 统计面板放到左上角
            console.log("x:"+container.offsetLeft+" ; y:"+container.offsetTop);
            // stats.domElement.style.position = 'absolute';//absolute
            stats.domElement.style.left = container.offsetLeft+'px';//'0px';//x
            stats.domElement.style.top = container.offsetTop+'px';//'0px';//y

            //缓存
            containerSize.w = container.offsetWidth;
            containerSize.h = container.offsetHeight;
        }
    // }
}

function animate() {
    requestAnimationFrame(animate);
    
    render();

    //监视
    stats.update();

    //物体运动
    TWEEN.update();
}

function render() {
    // renderCamera();//相机控制 

    renderRelation();//建立轴之间的连接关系
    
    renderLink();//关节控制:控制空间位置以及旋转

    //刷新
    camera.lookAt(cameraTarget);
    renderer.render(scene, camera);

    //检查窗口自适应初始化是否正常
    checkWindowResize();
}

function renderCamera() {
    if(cameraRun.runSwitch)
    {
        //获取一个时间值 可以控制旋转的速度
        var timer = Date.now() * 0.0001;
        //相机一直在变
        camera.position.x = Math.cos( timer ) * 3;
        camera.position.y = cameraPosition.y;//相机旋转过程中也可以改变y轴
        camera.position.z = Math.sin( timer ) * 3;

    }
    else
    {
        //触摸控制
        // controlsCamera.update();

        //gui控制 相机位置
        camera.position.x = cameraPosition.x;//position
        camera.position.y = cameraPosition.y;
        camera.position.z = cameraPosition.z;
    }

    //gui 改变相机朝向
    cameraTarget.set(cameraVector.x,cameraVector.y,cameraVector.z);//vector
}

function renderRelation(){
    //父子关系(不知道为何在init不可初始化)连杆
    if(!linkRelation)
    {
        for(var i = 1; i < robotLinkCount; i++)
        {
            //console.log('i:' + i);
            if(robotLink[i-1] && robotLink[i])
            {
                robotLink[i].parent = robotLink[i-1];
                robotLink[i-1].children = robotLink[i];
            }
            else
            {
                linkRelation = false;
                break;
            }
            linkRelation = true;
        }

        if(linkRelation)//连杆关系已经初始化完成
        {
            //目前下列模型只适合6轴
            for(var i = 0; i < robotLinkCount; i++)//关节
            {
                if(i > 0 && i < robotLinkCount-1)
                {
                    var name = "joint" + i;
                    controlsGui.addFolder( name );

                    if(i%2) //取模>0 即是 奇数
                    {
                        controlsGui.add(robotLinkRotation[i],"z",-10,10);
                    }
                    else
                    {
                        controlsGui.add(robotLinkRotation[i],"y",-10,10);
                    }
                }
                // else if(i == 0)//底座
                // {
                //     controlsGui.addFolder( "base" );
                //     controlsGui.add(robotLinkPosition[0],"x",-2,2);
                //     controlsGui.add(robotLinkPosition[0],"z",-2,2);
                // }
                // else//最后 手腕
                // {
                //     controlsGui.addFolder( "hand" );

                //     controlsGui.add(robotLinkRotation[robotLinkCount-1],"x",-10,10);
                // }
            }
        }
    }
}

function renderLink() {
    //如果设置的轴数与加载的对象数量一致才可以操作
    if(robotLinkCount == robotLink.length)
    {
        if(linkRandamRun.runSwitch)
        {
            for(var i = 1; i<robotLinkCount; i++) //  一般 底座不需要改变 因此从 1开始 
            {  
                // robotLink[i].rotation.x = robotLinkRotation[i].x;//x轴不会变化 因此也不需要赋值
                robotLink[i].rotation.y = robotLinkRotation[i].y;
                robotLink[i].rotation.z = robotLinkRotation[i].z;
            }
        }
        else
        {
            for(var i = 0; i<robotLinkCount; i++) //手动 可能需要调节底座
            {       
                robotLink[i].position.x = robotLinkPosition[i].x;//测试用 手动调整位置
                // robotLink[i].position.y = robotLinkPosition[i].y;
                robotLink[i].position.z = robotLinkPosition[i].z;

                //robotLinkRotation[i]获取的值为-10 到 10
                // robotLink[i].rotation.x = robotLinkRotation[i].x;
                robotLink[i].rotation.y = robotLinkRotation[i].y;
                robotLink[i].rotation.z = robotLinkRotation[i].z;
            }
        }
    }
}

function setupTweenJoint()
{
    var duration = getRandomInt( 3000, 5000 );//获取一个随机数 1000ms 1s //console.log(duration);

    var target = {};

    //linkRelation = true 连杆关系已经初始化完成
    //也就是意味着 所有关节对象都不为空
    if(linkRelation && linkRandamRun.runSwitch)
    {
        //获取所有关节信息
        for ( var i = 1; i < robotLinkCount-1 ; i ++ ) 
        {
            var old = tweenParameters[i];
            //old 为true时候 rotation = old false时rotation = robotLink[i].rotation
            if(i%2) //取模>0 即是 奇数
            {
                var rotation = old ? old : robotLinkRotation[i].z;
            }
            else
            {
                var rotation = old ? old : robotLinkRotation[i].y;
            }
            tweenParameters[i] = rotation;

            target[i]= getRandomInt( -Math.PI*(3/5), Math.PI*(3/5) );//z
        }
        
        //Linear一次函数, Quadratic二次, Cubic三次, Quartic四次
        kinematicsTween = new TWEEN.Tween( tweenParameters ).to( target, duration ).easing( TWEEN.Easing.Quadratic.Out );

        kinematicsTween.onUpdate( function() {

            for ( var i = 1; i < robotLinkCount-1 ; i ++ ) {
                if(i%2) //取模>0 即是 奇数
                {
                    robotLinkRotation[i].z = tweenParameters[i];
                }
                else
                {
                    robotLinkRotation[i].y = tweenParameters[i];
                }
            }

        } );

        kinematicsTween.start();
    }

    setTimeout( setupTweenJoint, duration );
}

function getRandomInt( min, max ) {
    return Math.floor( Math.random() * ( max - min + 1 ) ) + min;
}